home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Freaks Macintosh Archive
/
Freaks Macintosh Archive.bin
/
Freaks Macintosh Archives
/
Macintosh
/
Development & Resource Tools
/
Janus0.1.sit
/
Janus0.1
/
READ ME Janus 0.1
< prev
next >
Wrap
Text File
|
1997-10-18
|
14KB
|
337 lines
Janus 0.1 Release Notes / Documentation / Examples
Peter Creath
pjcreath@phoenix.princeton.edu
-------------------------------------------------------------------------
- What the hell is Janus?
Think of this as the PPC native equivalent of the ResEdit CODE editor.
In layman's terms, Janus is a fat binary (of course) which lets you find the
PowerPC native code corresponding to 680x0 code. Now you can patch your
favorite native games to give yourself infinite ammo and lives too!
NOTE: This is not for the faint of heart. If you can figure out the 680x0
patches on your own, this is for you. If not, find somebody who can.
In technical terms, Janus is (in its current incarnation) a reference tracer for
PowerPC-native code. This means it can search for references to a Toolbox
trap (aka "symbol" in the new PPC way of doing things) and references to a
subroutine, and can tell you what trap is being dispatched by what subroutine.
-------------------------------------------------------------------------
- Symbols? Trap dispatch subroutines? HUH?
If you REALLY understand how PPC native code works, you can probably skip this
section.
In the old 680x0 way of doing things, the opcodes from 0xA000 to 0xAFFF were
reserved for "A-Traps". Any A-Trap then called the subroutine referred to by the
trap table. Apple used this trap mechanism to implement their Toolbox. If you
have never seen _WaitNextEvent or _Debugger or some such, you need to brush up
on your 680x0 assembly.
In the PowerPC world, we still have traps, but Apple decided to do something a
little more clever. Patching traps is a pain in the ass, and is slow. Traps are
essential shared code, so why not have a universal dispatcher for generic symbols
and dispatch traps that way? This is exactly what Apple did.
When a PowerPC native program wishes to call a trap, it sets up the function
parameters in typical PPC calling fashion, then it sets two registers to the
first 8 bytes of the trap name. (ie: "WaitNext") This small fragment of code
(which is generated for each trap used) is called the symbol (or trap) glue.
In addition, when a PPC native application launches, it exports a symbol table
(part of the as-of-yet-undocumented PEF format) which the Code Fragment
Manager checks to make sure it can resolve all the symbols. (ie: It makes
sure it knows how to handle Debugger or ParamText, or whatever else
may be exported).
This is where Janus comes in.
-------------------------------------------------------------------------
- What does Janus do?
Janus reads in the PEF symbol table and lets you do all sorts of nifty stuff with
it:
o You can list all the symbols and their associated numbers. This, if nothing
else, tells you what traps are being called in the program. (You also
need the trap numbers for the other cool stuff you can do.)
o You can search for references to the symbols (or, actually, their
glue code). In other words, if you enter in the symbol number for
GetNextEvent, it will show you every place GetNextEvent() is called
in the native code.
o You can find out what symbol is called by a specific glue routine.
o You can search for references to any subroutine at all.
-------------------------------------------------------------------------
- Why do I care?
Well, there is no native PPC debugger (a la MacsBug). OK, so I lied, there is a
2-machine debugger, but not all of us have the luxury of having two machines
adjacent and networked. This makes patching native code a real hassle (or
impossibility usually).
There's also no native equivalent to the ResEdit CODE editor, with its
searching for references and such.
What you can do now is, once you have made a patch to 680x0 code, you can
search around your patch for "landmarks", the most convenient of which
are traps (or symbols). Then you search for those same landmarks in the
native code using Janus, thereby narrowing down your search to a few
dozen native instructions (if you're lucky). Naturally, things aren't always
this easy, but this does cover the bulk of native software out there.
-------------------------------------------------------------------------
- General instructions
I use PowerPCdisas for my native code wanderings. Hence, Janus prints
the code offsets in terms of their position in the data fork (not their position
in the PEF container).
-------------------------------------------------------------------------
- Patching and native code tips, etc.
4800xxxx is a BRA statement
60000000 is a NOP statement
"mflr" occurrs at the beginning of every subroutine
"blr" occurs at the end of every subroutine
There are often many return points within a subroutine. In 68k code, there
was usually just one RTS. In native code, rather than BRA to the end (over
a bunch of code), it just RTS's immediately.
Code within segments is (so far) always in the same order in 68k & PPC
native, however the native code IS NOT ALWAYS in the same order as
the segments themselves. In other words, your PPC code could have
the equivalent object code to segment 10, then 3, then 4, then 7, then
1, and so on. Thus, if you're having trouble finding a piece of equivalent
code, look for landmarks near the beginning and end of your code segment
and find out where your code segment is in the native code. (This is
a generally useful practice, as correlating hundreds of occurrences of
traps can be hard on the eyes!)
You definitely need the Motorola PowerPC™ 601 User's Manual. It's about
$5 or so (or whatever shipping costs).
(IBM part # 52G7484, (800) 769-3772)
(Motorola part # MPC601UM/AD, (800) 521-6274)
-------------------------------------------------------------------------
- Limitations, future plans, etc.
o Janus only reads PEF (not XCOFF) files.
o Janus only looks in applications with the native code in the data fork.
o Janus only looks in the first code container in the PEF.
o Janus needs enough RAM to read in the entire code fragment.
o If I run across some XCOFF files (enough to reverse engineer Apple's
implementation), I will add that functionality.
o If you find non-applications with PEF data, let me know.
o If you find any applications with more than one code container, let
me know.
o I will leave the RAM requirement as-is, for speed reasons.
Originally, this was going to entirely automate the matching process between
68k code and PowerPC native code. However, the need for SOME utility forced
me to throw together the components I had finished and toss it out the door.
That and the lack of interface make this version 0.1. 1.0 should automate
the task and save a data file (which will also allow you to match code between
versions, so you don't have to re-find your patch for each release). It'll also
have an interface.
Hopefully, I'll also have a built-in disassembler (and possibly assembler) in
1.0. This isn't entirely equivalent to ResEdit's CODE editor right now -- it
just does the same thing as far as searching for references and such.
-------------------------------------------------------------------------
- Some examples of Janus in action, to give you a feel of how to use it.
Case Study: Game-cheating patches to Pathways Into Darkness 2.0 (fat)
Janus won't help you find the 68k code to patch, so I've provided the 68k patches
already. I walk you through 2 patches, showing you how to find the native code
corresponding to the patched areas and tell you how to patch them (w/ HexEdit).
--------------------------
First patch: We'd like to be invulnerable, so we need to axe the subtraction
command at CODE 6+22B4 (which is done in the 680x0 code by NOP'ing it out). So
let's try to find the corresponding code in the PPC native code.
Unfortunately, CODE 6 doesn't have an trap calls in it, so we can't use the direct
method (which would be looking for distinctive traps surrounding the code in
question). We're interested in 6+22B4, which is closely followed by a JSR to
CODE 3+1CBA. This looks a bit more promising, being preceded by some good
traps.
DrawString:
0x0000D46C
0x0000D52C
0x0000DCA4
0x0000DD6C
0x0000DE54
0x0000E878
0x0000E9E0
0x0000EB84
0x0000ED94
0x0000F4B8
0x0000F6A4
0x0000F7F0
0x0000FC24
0x0000FE78
0x000102A4
0x000103C0
0x00010A3C
0x00010A6C
0x00011098
0x000114F8
0x00015234 x
0x0001FB18 x
0x00022B08 x
Well, that's a pretty large number, but we can eliminate the last three, since
they're all fairly far from any other occurrence of DrawString. Still too
many though...
So let's look back a ways and see if there are any interesting traps. Too many
StringWidths near DrawStrings to be of use... But the GetMainDevice and
NewCWindow at 3+1966 and 3+19AC look good.
GetMainDevice:
0x0000D1F8
0x0000D2A8
0x0000F910
0x0000F9B8
0x00010D70
0x00010DF4
0x00011688
0x000116B0
0x000129FC
0x00012BD8
0x00013BF0
0x00013FD0
0x000179A4
0x0002FCA0
0x0002FCC8
0x00031874
0x00031BBC
0x00031BE0
0x00032B4C
0x00032BD8
NewCWindow:
0x0000D324
0x0000FA64
0x00010E68
0x00012AB4
0x00017A18
0x00022D64
Hmm. I would've expected more NewCWindow's than GetMainDevices...
Well, there's still a fair number left, so lets see how many of these have
OffsetRects sandwiching the GetMainDevice. (Note the JSR code 2+20D0
at 3+19BE = 0x0001DA3C...we'll use that for our next patch)
OffsetRect: GetMainDevice: OffsetRect: GetMainDevice: OffsetRect: NewCWindow:
(none) 0x0000D1F8 0x0000D2A0 0x0000D2A8 0x0000D2E0 0x0000D324 x
0x0000F978 0x0000F910 0x0000F9B0 0x0000F9B8 0x0000F9F0 0x0000FA64
(none) 0x00010D70 0x00010DCC 0x00010DF4 0x00010E2C 0x00010E68 x
(none) 0x000129F4 0x000129FC 0x00012A38 0x00012AB4 x
(none) 0x00179A4 0x00017C8C 0x00017A18 x
(none) 0x00022D64 x
So now we know where 3+19AC is: 0x0000FA64. So let's look for
subroutines after that. Well, we see the CloseWindow, but no SetWTitle...
Well, let's just keep looking past this mammoth subroutine 'til we find another
subroutine and try to regain our bearings. Ah, here's one at 0x0000FFC4.
It does a GetPort, SetPort, SetRect, then a JSR. Well, that looks an awful lot
like 3+1CBA, especially with the parameters passed to the JSR (0xE8 and
0x14). How convenient. (And yes, there is still some guesswork involved.)
Now let's ask Janus & ResEdit what references there are to this subroutine:
0x0001040C 3+1A48
0x0002776C 6+076E
0x00029D54 6+20B8
0x00029EA8 6+21E2
0x0002A034 6+22D4
Luckily enough, it's pretty obvious which subroutines here correlate to the
references listed by ResEdit's CODE editor. We want 6+22D4, so let's look
around 0x0002A034. Look up a little bit, and look, there's our subtraction
command at 0x0002A004. Well, the easiest way to bypass this is to avoid the
storage of the new value back in 60(R3), so NOP out that command.
Change: 0x002A008 from 0xB0C30060 to 60000000
Effect: Invulnerability. You still say "ouch", but you don't lose any health.
--------------------------
Second patch: Don't you hate having to be on the little red runes in order to
save? Let's fix that. The 680x0 code is at CODE 2+0728. We need to axe
the branch statement with a NOP.
Well, it looks like we won't even need that CODE 2 we noticed above, since
there's an OpenDeskAcc just above at 2+06EA. That's pretty distinctive.
And sure enough, Janus only finds one occurrence of it at 0x000195A8.
So we slowly work our way down both sets of code (a large monitor really
helps here!). Notice that the method of implementing a jump table in PPC code
is to use a blr instruction (being preceded by something other than mtlr R0).
Well, the inline jump table could make things sticky, so let's look for the first
occurrence of TickCount just after the OpenDeskAcc: 0x000195F8. Look
above a little bit, past the branch and JSR and you see the branch we'd like
to get rid of at 0x000195E4.
Change: 0x000195E4 from 0x41820028 to 60000000
Effect: You can save anywhere.
--------------------------
Some more patches you can practice on:
Infinite crystal life: 7+3EE0 D16B 0004 -> 4E71 4E71
Ammo-less monsters: 7+0610 4EBA 0C1C -> 4E71 4E71
7+11F4 4EBA 0038 -> 4E71 4E71
Infinite ammo: 7+415A 9F6A 0004 -> 4E71 4E71
And since CODE 7 doesn't contain any traps, you'll have to use the same kind of
strategy I used for the first patch above...
-------------------------------------------------------------------------
- Epilogue
If you have any questions, comments, suggestions, etc., feel free to send me
e-mail at pjcreath@phoenix.princeton.edu
- Peter
-------------------------------------------------------------------------
(Paranoid) DISCLAIMER:
Layman's summary:
The program should work, but if it crashes, you get what you pay for.
I can't control what people do with this program, nor can I be held liable
for their actions.
Legalese:
THE AUTHOR (Peter J. Creath) MAKES NO WARRANTY OR REPRESENTATION,
EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE, ITS QUALITY,
PERFORMANCE, MARCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
AS A RESULT, THIS SOFTWARE AND ACCOMPANYING DOCUMENTATION IS
PROVIDED "AS IS," AND YOU THE USER ARE ASSUMING THE ENTIRE RISK AS
TO ITS QUALITY AND PERFORMANCE.
IN NO EVENT WILL THE AUTHOR (Peter J. Creath) BE LIABLE FOR ANY
CONSEQUENTIAL, INCIDENTAL OR INDIRECT DAMAGES (INCLUDING DAMAGES
FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
INFORMATION, AND THE LIKE) ARISING OUT OF THE USE OF OR INABILITY TO USE
THE SOFTWARE OR ACCOMPANYING DOCUMENTATION EVEN IF THE AUTHOR
(Peter J. Creath) HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
The author's liability for actual damages for any cause whatsoever,
and regardless of the form of the action, will be limited to the purchase price
of the Software ($0.00).